package com.bw.ai.service;

import com.alibaba.fastjson.JSONObject;
import com.bw.ai.domain.Doctor;
import com.bw.ai.mapper.AiMapper;
import com.google.gson.Gson;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
public class VectorService {

    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private AiMapper aiMapper;
    // 存储向量到Redis
    public void storeVector(String key, List<Doctor> vector) {
        // 将向量序列化为字符串或其他可存储的格式（如JSON）
        Gson gson = new Gson();
        String json = gson.toJson(vector);
        redisTemplate.opsForValue().set(key, json);
    }

    // 查询与给定向量最相似的K个向量
    public List<String> similaritySearch(double[] queryVector, int k) {
        // 将查询向量转换为与存储在Redis中相同格式的字符串（可选）
        String queryVectorStr = Arrays.toString(queryVector);

        // 使用Redis的搜索功能进行相似性搜索（这里需要实现具体的搜索逻辑）
        // 假设有一个`vectorStore.similaritySearch`方法可以进行相似性计算
        // List<Document> results = vectorStore.similaritySearch(queryVector, k);
        // 返回结果（这里仅为示例，实际应返回相似向量的键或其他相关信息）
        // return results.stream().map(Document::getKey).collect(Collectors.toList());

        // 由于Redis原生不支持向量搜索，这里可以使用第三方库或自定义实现
        // 以下是一个简单的示例，使用余弦相似度进行手动计算（不推荐用于生产环境）
        Map<String, Double> similarityMap = new HashMap<>();
        redisTemplate.keys("*").forEach(redisKey -> {
            String vectorStr = (String) redisTemplate.opsForValue().get(redisKey);
            double[] storedVector = Arrays.stream(vectorStr.replaceAll("[\\[\\]\\s]", "").split(","))
                    .mapToDouble(Double::parseDouble).toArray();
            double similarity = cosineSimilarity(queryVector, storedVector);
            similarityMap.put(redisKey, similarity);
        });

        // 按相似度排序并返回前K个结果
        List<Map.Entry<String, Double>> sortedEntries = similarityMap.entrySet().stream()
                .sorted((e1, e2) -> Double.compare(e2.getValue(), e1.getValue()))
                .collect(Collectors.toList());

        return sortedEntries.stream().limit(k).map(Map.Entry::getKey).collect(Collectors.toList());
    }

    // 计算余弦相似度
    private double cosineSimilarity(double[] a, double[] b) {
        double dotProduct = 0.0;
        double normA = 0.0;
        double normB = 0.0;
        for (int i = 0; i < a.length; i++) {
            dotProduct += a[i] * b[i];
            normA += a[i] * a[i];
            normB += b[i] * b[i];
        }
        return dotProduct / (Math.sqrt(normA) * Math.sqrt(normB));
    }
}
